package com.desaysv.svview

import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.TypedArray
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.RelativeLayout
import com.desaysv.svview.databinding.LayoutSwitchButtonBinding
import java.util.concurrent.atomic.AtomicBoolean

@SuppressLint("CustomViewStyleable")
class SwitchButton @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attributeSet, defStyleAttr) {
    companion object {
        private const val TAG = "SwitchButton"
    }

    private val binding = LayoutSwitchButtonBinding.inflate(LayoutInflater.from(context))

    private var pointMargin = -1
    private var pointWidth = -1
    private var defaultBg = -1
    private var selectedBg = -1
    private var pointBg = -1
    private var bgHeight = -1


    private var defaultBgColor = -1
    private var selectedBgColor = -1
    private var pointBgColor = -1


    private var animatorDuring = 100


    private val isSelected = AtomicBoolean(false)

    init {
        attributeSet?.let {
            val typedArray: TypedArray =
                context.obtainStyledAttributes(it, R.styleable.SwitchButton)
            pointMargin =
                typedArray.getDimensionPixelSize(R.styleable.SwitchButton_point_margin, -1)
            pointBg = typedArray.getResourceId(R.styleable.SwitchButton_point_bg, -1)
            defaultBg = typedArray.getResourceId(R.styleable.SwitchButton_default_bg, -1)
            selectedBg = typedArray.getResourceId(R.styleable.SwitchButton_selected_bg, -1)
            bgHeight = typedArray.getDimensionPixelSize(R.styleable.SwitchButton_bg_height, -1)
            animatorDuring = typedArray.getInt(R.styleable.SwitchButton_switch_during, 100)


            pointBgColor = typedArray.getColor(R.styleable.SwitchButton_point_bg_color, Color.parseColor("#ffffff"))
            defaultBgColor = typedArray.getColor(R.styleable.SwitchButton_default_bg_color, Color.parseColor("#dddddd"))
            selectedBgColor = typedArray.getColor(R.styleable.SwitchButton_selected_bg_color, Color.parseColor("#ff55ff"))

            isSelected.set(typedArray.getBoolean(R.styleable.SwitchButton_selected, false))

            typedArray.recycle()
        }

        val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        this.orientation = HORIZONTAL
        addView(binding.root, layoutParams)
    }

    private var width = 0
    private var height = 0

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //测量控件的真实高度
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        if (width == 0 || height == 0) {
            return
        }
        if (width == this.width && height == this.height) {
            return
        }
        this.width = width
        this.height = height
        Log.i(TAG, "onMeasure: width=$width , height=$height")
        //根据真实高度重新设置大小
        resize()
    }

    private fun resize() {
        //先配置背景
        setCornerRadius(height.toFloat())
        //配置间距
        if (pointMargin == -1) {
            pointMargin = (height * 0.1f).toInt()
        }
        (binding.ivPoint.layoutParams as RelativeLayout.LayoutParams).setMargins(
            pointMargin,
            pointMargin,
            pointMargin,
            pointMargin
        )
        //配置point的宽高
        if (pointWidth == -1) {
            pointWidth = height - pointMargin * 2
            binding.ivPoint.layoutParams.width = pointWidth
            binding.ivPoint.layoutParams.height = pointWidth
            if (!isSelected.get()) {
                binding.ivSelectedBg.layoutParams.width = pointWidth + pointMargin * 2
            } else {
                binding.ivSelectedBg.layoutParams.width = width
            }
        }
        //配置背景的高度
        if (bgHeight != -1) {
            binding.ivDefaultBg.layoutParams.height = bgHeight
            binding.ivSelectedBg.layoutParams.height = bgHeight
        }
        changeSelected(false)
    }

    private var selectBgAnimator: Animator? = null
    override fun onFinishInflate() {
        super.onFinishInflate()
        binding.ivSelectedBg.visibility = if (isSelected.get()) {
            VISIBLE
        } else {
            GONE
        }
        this.setOnClickListener {
            if (selectBgAnimator != null && selectBgAnimator!!.isRunning) {
                Log.e(TAG, "onFinishInflate: had in selecting")
                return@setOnClickListener
            }
            isSelected.set(!isSelected.get())
            changeSelected()
        }
    }

    interface OnSelectedChangeListener {
        fun onSelectedChange(isSelected: Boolean)
    }

    private var onSelectedChangeListener: OnSelectedChangeListener? = null
    fun setOnSelectedChangeListener(listener: OnSelectedChangeListener) {
        this.onSelectedChangeListener = listener
    }

    fun switch() {
        post {
            if (selectBgAnimator != null && selectBgAnimator!!.isRunning) {
                Log.e(TAG, "switch: had in selecting")
                return@post
            }
            isSelected.set(!isSelected.get())
            changeSelected()
        }
    }

    fun isSwitch(): Boolean {
        return isSelected.get()
    }

    private fun changeSelected(withAnimator:Boolean=true) {
        val targetX = if (isSelected.get()) {
            if(!withAnimator){
                width - binding.ivPoint.layoutParams.width.toFloat() - pointMargin *2
            }else{
                width - binding.ivPoint.layoutParams.width.toFloat() - pointMargin
            }
        } else {
            if(!withAnimator){
                0f
            }else{
                0f + pointMargin
            }
        }

        val targetWidth = if (isSelected.get()) {
            width
        } else {
            pointWidth + pointMargin * 2
        }
        val currentWidth = if (isSelected.get()) {
            pointWidth + pointMargin * 2
        } else {
            width
        }
        //如果不需要动画，就要直接显示到指定位置
        if(!withAnimator){
            binding.ivPoint.x = targetX
            binding.ivSelectedBg.layoutParams.width = targetWidth
            return
        }
        binding.ivPoint.animate().x(targetX).setDuration(animatorDuring.toLong()).start()

        selectBgAnimator?.cancel()
        selectBgAnimator = ValueAnimator.ofInt(currentWidth, targetWidth).apply {
            duration = animatorDuring.toLong()
            addUpdateListener {
                binding.ivSelectedBg.layoutParams.width = it.animatedValue as Int
                binding.ivSelectedBg.requestLayout()
            }
            addListener(object : Animator.AnimatorListener {
                override fun onAnimationStart(animation: Animator) {
                    if (isSelected.get()) {
                        binding.ivSelectedBg.alpha = 0f
                        binding.ivSelectedBg.visibility = VISIBLE
                        binding.ivSelectedBg.animate().alpha(1f).setDuration(50).start()
                    }
                }

                override fun onAnimationEnd(animation: Animator) {
                    if (!isSelected.get()) {
                        binding.ivSelectedBg.alpha = 1f
                        binding.ivSelectedBg.visibility = GONE
                        binding.ivSelectedBg.animate().alpha(0f).setDuration(50).start()
                    }
                    binding.ivPoint.isSelected = isSelected.get()
                    onSelectedChangeListener?.onSelectedChange(isSelected.get())
                }

                override fun onAnimationCancel(animation: Animator) {
                }

                override fun onAnimationRepeat(animation: Animator) {
                }

            })
            start()
        }
    }

    // 添加设置圆角的方法
    private fun setCornerRadius(radius: Float) {
        if (defaultBg != -1) {
            binding.ivDefaultBg.setBackgroundResource(defaultBg)
        }
        if (selectedBg != -1) {
            binding.ivSelectedBg.setBackgroundResource(selectedBg)
        }
        if (pointBg != -1) {
            binding.ivPoint.setBackgroundResource(pointBg)
        }
        if (binding.ivDefaultBg.background == null) {
            // 修改默认背景的圆角
            val defaultBackground = GradientDrawable().apply {
                setColor(defaultBgColor)
                shape = GradientDrawable.RECTANGLE
                cornerRadius = radius
            }
            binding.ivDefaultBg.background = defaultBackground
        }
        if (binding.ivSelectedBg.background == null) {
            // 修改选中背景的圆角
            val selectedBackground = GradientDrawable().apply {
                setColor(selectedBgColor)
                shape = GradientDrawable.RECTANGLE
                cornerRadius = radius
            }
            binding.ivSelectedBg.background = selectedBackground
        }

        if (binding.ivPoint.background == null) {
            val pointDrawable = GradientDrawable().apply {
                setColor(pointBgColor)
                shape = GradientDrawable.OVAL
            }
            binding.ivPoint.background = pointDrawable
        }
    }
}